home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
ASTRNOMY
/
SFS101S.ZIP
/
RO101.ZIP
/
RO_MACR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-04
|
15KB
|
644 lines
/********************************************************/
/* */
/* ro_macr.c macro and diversion routines */
/* for ro */
/* */
/* ro version 1.10 */
/* */
/* Portions copyright (c) 1989 by Ted A. Campbell */
/* Bywater Software */
/* P. O. Box 4023 */
/* Duke Station */
/* Durham, NC 27706 */
/* */
/* Contains portions of ROFF4, Version 1.60 */
/* (c) 1983, 4 by Ernest E. Bergmann */
/* Physics, Building #16 */
/* Lehigh University */
/* Bethlehem, Pa. 18015 */
/* */
/* Contains portions of ROFF4, Version 1.61 */
/* (c) 1985 by Konrad Kwok */
/* 20 3rd Street, Section M */
/* Fariview Park, */
/* Hong Kong */
/* */
/* ro and its predecessor ROFF4 are based on */
/* the ROFF text processor described in Kernigan */
/* and Plauger's now-classic text <Software Tools> */
/* */
/* Permission is hereby granted for all commercial and */
/* non-commercial reproduction and distribution of this */
/* material provided this notice is included. */
/* */
/********************************************************/
#include "ro.h"
/********************************************/
/* insert() -- process .ds command */
/* takes a command line in ro_curline and adds its
entry to the table */
insert()
{
static char name[ LSZ ];
register int n;
char c, *l;
struct divfd *sptr;
/*pass over command*/
l = ro_curline;
for ( c = *l; c != ' ' && c != '\n' && c != '\t'; l++ )
{
c = *l;
}
/*advance to first non-blank */
for ( ; c == ' ' || c == '\t'; l++ )
{
c = *l;
}
if ( c == '\n' )
{
if ( ro_verbose == TRUE )
{
fprintf( stderr, ".ds: no arguments \n" );
}
return -1;
}
/* get the name of the macro into the buffer */
n = 0;
--l;
do
{
name[ n ] = *l;
++l;
++n;
}
while( *l != ' ' && *l != '\t' && *l != '\n' );
name[ n ] = '\0'; /* terminate name with \0 */
if ( strlen( name ) > 2 )
{
name[ 2 ] = '\0';
if ( ro_verbose == TRUE )
{
fprintf( stderr, ".ds: string name over two characters, shortened to <%s>. \n",
name );
}
}
/*advance to first non-blank */
c = *l;
for ( ; c == ' ' || c == '\t'; l++ )
{
c = *l;
}
if ( c == '\n' )
{
if ( ro_verbose == TRUE )
{
fprintf( stderr, ".ds: no string argument \n" );
}
return -1;
}
/* now get the string itself into the tbuf buffer */
if (( c == '\"' ) || ( c == '\'' ))
{
n = 0;
do
{
tbuf[ n ] = *l;
++l;
++n;
}
while( *l != c );
tbuf[ n ] = '\0'; /* terminate name with \0 */
}
else
{
n = 0;
do
{
tbuf[ n ] = *l;
++l;
++n;
}
while( *l != ' ' && *l != '\t' && *l != '\n' );
tbuf[ n ] = '\0'; /* terminate name with \0 */
}
/* see if it is already defined */
if( ( sptr = find2( name, slink )) != NULL )
{
if ( ro_verbose == TRUE )
{
fprintf( stderr, "%cWarning: <%s> was defined to be <%s>\n",
/* BELL, name, sptr->mstr );
brachet@imag.imag.fr 05/17/90
*/
BELL, name, (sptr->mstr ? sptr->mstr : "" ));
fprintf( stderr, "...now it is defined to be <%s>\n", tbuf );
}
}
else
{
if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
{
fprintf( stderr, "Fatal error: cannot allocate memory for insertion structure. \n" );
exit ( -1 );
}
/* allocation succeeded, set up links */
sptr->prev = slink; /* save previous link */
slink = sptr; /* reset link */
strcpy( sptr->nm, name );
sptr->mstr = NULL;
}
/* allocate memory for the new string if it is longer
than the current string */
if ( sptr->mstr == NULL || strlen( tbuf ) > strlen( sptr->mstr ) )
{
if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
{
fprintf( stderr, "Fatal error: failed to allocate memory for string. \n" );
exit( -1 );
}
}
/* copy the string to the new memory */
strcpy( sptr->mstr, tbuf );
}
/****************************************/
showit() /* displays the list of entries in the string
substitution table pointed to by HEAD. */
{
struct divfd *pw;
fprintf( stderr, "Strings defined:\n");
dashes();
pw = slink;
while( pw != NULL )
{
fprintf( stderr, "%s:\t<%s> \n", pw->nm, pw->mstr );
pw = pw->prev;
}
dashes();
}
/****************************************/
putback( c ) /*cf K & P, p256*/
char c;
{
if ( ++ro_binp >= BACKSIZE )
{
fprintf( stderr, "Fatal error: too many characters pushed back\n");
exit( -1 );
}
ro_backbuf[ ro_binp ] = c;
}
/** add by Conrad Kwok. 9th Sept.,84 ****/
pbmac( s, sl ) /* s = pointer to macro text */
char s[], sl[]; /* sl = current line */
{
static char *parms[10], dupln[LSZ];
register int i;
strcpy( dupln, sl ); /* get a copy of the current line */
setparm( dupln, parms );
for ( i = strlen(s)-1; i >= 0; )
{
if ( isdigit( s[i] ))
{
if ( i > 0 && s[ i - 1 ] == '$' )
{
pbstr( parms[ s[i--] & 0x0f ]);
--i;
}
else
{
putback( s[i--] );
}
}
else
{
putback( s[i--] );
}
}
}
setparm( sl, parms)
char *sl, *parms[];
{
char a,c;
int nuparm;
for ( c = *sl; c != ' ' && c != '\n' && c != '\t'; )
{
c = *++sl;
}
while ( c == ' ' || c == '\t' )
{
c = *++sl;
}
for ( nuparm = 0; nuparm < 10; )
{
if (!(isalnum(c) || (c=='+') || (c=='-')))
{
sl++;
}
else
{
c = ' ';
}
parms[ nuparm++ ] = sl;
for ( a = *sl; a != c && a != '\n' && a != '\0'; )
{
if ( c == ' ' && a == '\t' )
{
break;
}
else
{
a = *++sl;
}
}
*sl = '\0';
c = a;
if ( a != '\0' && a != '\n')
{
while ( c == ' ' || c == '\t')
{
c = *++sl;
}
}
}
}
/****************************************/
pbstr( s ) /*put back string on input; cf K&P,p257*/
char s[LSZ];
{
int i;
for ( i = strlen(s); i > 0; )
{
putback( s[--i] );
}
}
/****************************************************************
ro_expand() Expand a macro
****************************************************************/
ro_expand()
{
char c, d, name[ 36 ];
register int n;
struct divfd *sptr;
c = ro_getch();
switch( c )
{
case BACKSLASH:
return PASSBACK; /* pass literal backslash
through the system */
break;
case '*': /* expand defined string */
d = ro_getch();
if ( d == '(' ) /* two-letter name */
{
name[ 0 ] = ro_getch();
name[ 1 ] = ro_getch();
name[ 2 ] = '\0';
}
else /* one-character name */
{
name[ 0 ] = d;
name[ 1 ] = '\0';
}
if ( ( sptr = find2( name, slink )) == NULL )
{
if ( ro_verbose == TRUE )
{
fprintf( stderr, "ro: failed to find string name <%s> \n",
name );
}
}
else
{
/* n = strlen( sptr->mstr ) - 1;
brachet@imag.imag.fr 05/17/90
*/
n = (sptr->mstr ? strlen( sptr->mstr ) - 1 : 0 );
while( n >= 0 )
{
putback( sptr->mstr[ n ] );
--n;
}
}
break;
case 'n': /* expand number register */
d = ro_getch();
if ( d == '(' ) /* two-letter name */
{
name[ 0 ] = ro_getch();
name[ 1 ] = ro_getch();
name[ 2 ] = '\0';
}
else /* one-character name */
{
name[ 0 ] = d;
name[ 1 ] = '\0';
}
if ( ( sptr = find2( name, rlink )) == NULL )
{
if ( ro_verbose == TRUE )
{
fprintf( stderr, "ro: failed to find register name <%s> \n",
name );
}
}
else
{
sprintf( tbuf, "%d", sptr->val );
n = strlen( tbuf ) - 1;
while( n >= 0 )
{
putback( tbuf[ n ] );
--n;
}
}
break;
case 'u': /* Half-line up */
putback( HALFUP );
putback( ESCAPE );
break;
case 'd': /* Half-line down */
putback( HALFDOWN );
putback( ESCAPE );
break;
case 'f': /* switch font */
d = ro_getch();
switch( d )
{
case 'R':
putback( ROMAN );
putback( ESCAPE );
break;
case 'I':
putback( ITALIC );
putback( ESCAPE );
break;
case 'B':
putback( BOLD );
putback( ESCAPE );
break;
default:
if ( ro_verbose == TRUE )
{
fprintf( stderr,
"ro: unrecognized font name \"%c\" in input stream. \n",
d );
}
}
break;
default:
putback( c );
break;
}
return TRUE;
}
/****************************************/
/* takes a .de and following lines and places
the information in the table; no macro
definition nesting permitted */
minsert()
{
register int n;
static char c, *src, *dst;
int keepon;
struct divfd *sptr;
#ifdef DEBUG
if ( ro_debug == TRUE )
{
fprintf( stderr, "DEBUG: enter minsert() \n" );
}
#endif
/* pass over command and following white space */
for ( src = ro_curline, c = *src; (c != ' ' ) && (c!='\n') && (c!='\t'); src++ )
{
c = *src;
}
for ( ; (c == ' ') || (c == '\t'); src++ )
{
c = *src;
}
/* Check to see if there is a name for the macro */
if ( ( c == '\n' ) || ( c == '\0' ))
{
if ( ro_verbose )
{
fprintf( stderr, "ERROR: .de: no name given. \n");
}
return -1;
}
/* Name detected, proceed to store the name */
else
{
#ifdef DEBUG
if ( ro_debug == TRUE )
{
fprintf( stderr, "DEBUG: macro name found; prepare to allocate memory. \n" );
}
#endif
if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
{
fprintf( stderr, "FATAL ERROR: cannot allocate memory for macro definition structure. \n" );
exit ( -1 );
}
#ifdef DEBUG
if ( ro_debug == TRUE )
{
fprintf( stderr, "DEBUG: memory allocated for macro.\n" );
}
#endif
sptr->prev = mlink; /* save previous link */
mlink = sptr; /* set mlink to this */
n = 0;
while( class( c ) == BLACK ) /* Store each character */
{ /* of the macro name */
sptr->nm[ n++ ] = c;
c = *( src++ );
}
sptr->nm[ n ] = '\0';
#ifdef DEBUG
if ( ro_debug == TRUE )
{
fprintf( stderr, "DEBUG: new macro name is <%s> \n",
sptr->nm );
}
#endif
}
/* Now read from instream until end of macro or EOF */
dst = tbuf;
keepon = 1;
while( keepon == 1 )
{
ro_gets( ro_curline );
src = ro_curline;
/* Check for end of macro */
if (( ro_curline[0] == COMMAND) && ( comtyp( ro_curline ) == EM ))
{
keepon = 0;
}
else /* Not end; transfer to buffer */
{
transfer( &src, &dst, (char) '\0' );
*(dst - 1) = '\n'; /* put a LF at the end */
*dst = 0; /* and a temp. delimiter */
}
#ifdef DEBUG
if ( ro_debug == TRUE )
{
fprintf( stderr, "DEBUG: minsert() current line <%s> \n",
tbuf );
}
#endif
}
*( dst ) = '\0'; /* Terminate with \0 */
#ifdef DEBUG
if ( ro_debug == TRUE )
{
fprintf( stderr, "DEBUG: text of new macro is <%s> \n", tbuf );
}
#endif
/* allocate memory for this macro string and transfer the string to
the new location */
if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
{
fprintf( stderr, "Fatal error: failed to allocate memory for macro string. \n" );
exit( -1 );
}
strcpy( sptr->mstr, tbuf );
}
/****************************************/
showm() /*lists macro definitions*/
{
struct divfd *pw;
fprintf( stderr, "MACROS DEFINED:\n");
pw = mlink;
while ( pw != NULL )
{
fprintf( stderr, "\t.%s\t<%s>\n", pw->nm, pw->mstr );
pw = pw->prev;
}
dashes();
}
/****************************************/
char *macq( line ) /*looks up name to see if it is a macro
definition. If it is, returns the
corresponding string, else returns
FALSE.
*/
char *line;
{
char c, *pc, wb[ LSZ ];
struct divfd *pstr;
pc = wb;
while ( class( c = *( ++line )) == BLACK )
{
*( pc++ ) = c;
}
*pc='\0';
pstr = find2( wb, mlink );
if ( pstr == NULL )
{
return NULL;
}
else
{
return ( pstr->mstr );
}
}
/****************************************/
struct divfd *
find2( s, link) /* finds or doesn't find s in table
of substitutions pointed to by link */
char *s;
struct divfd *link;
{
struct divfd *l;
l = link;
while ( l != NULL )
{
if ( !strcmp( s, l->nm ) )
{
return( l ); /* return structure pointer */
}
l = l->prev;
}
return( NULL ); /* failed */
}
/****************************************/